/**
* Copyright 2009 Roland Foerther, Carl-Eric-Menzel, Olaf Siefart
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.senacor.wbs.web.project;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.markup.html.tree.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.tree.table.ColumnLocation;
import org.apache.wicket.extensions.markup.html.tree.table.IColumn;
import org.apache.wicket.extensions.markup.html.tree.table.IRenderable;
import org.apache.wicket.extensions.markup.html.tree.table.PropertyTreeColumn;
import org.apache.wicket.extensions.markup.html.tree.table.TreeTable;
import org.apache.wicket.extensions.markup.html.tree.table.ColumnLocation.Alignment;
import org.apache.wicket.extensions.markup.html.tree.table.ColumnLocation.Unit;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.html.tree.AbstractTree;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import com.senacor.domain.project.Project;
import com.senacor.domain.project.Task;
import com.senacor.domain.project.TaskManager;
import com.senacor.domain.project.TaskStatus;
public class EditableTreeTablePanel extends Panel {
private static final ResourceReference ADD = new ResourceReference(EditableTreeTablePanel.class, "res/add.png");
private static final ResourceReference GO_BUTTOM = new ResourceReference(EditableTreeTablePanel.class, "res/go-bottom.png");
private static final ResourceReference GO_DOWN = new ResourceReference(EditableTreeTablePanel.class, "res/go-down.png");
private static final ResourceReference GO_TOP = new ResourceReference(EditableTreeTablePanel.class, "res/go-top.png");
private static final ResourceReference GO_UP = new ResourceReference(EditableTreeTablePanel.class, "res/go-up.png");
private static final ResourceReference REMOVE = new ResourceReference(EditableTreeTablePanel.class, "res/remove.png");
@SpringBean()
private TaskManager taskManager;
private TreeTable tree;
private DefaultTreeModel defaultTreeModel;
private final Project project;
public EditableTreeTablePanel(String id, Project project) {
super(id);
this.project = project;
List<Task> tasks = taskManager.findTasks(project);
IColumn columns[] = new IColumn[] {
new PropertyTreeColumn(new ColumnLocation(Alignment.LEFT, 10, Unit.EM), "Tree Column", "userObject.id"),
new EditableTextFieldColumn(new ColumnLocation(Alignment.LEFT, 6, Unit.EM), "Name", "userObject.name"),
new EditableTextFieldColumn(new ColumnLocation(Alignment.MIDDLE, 30, Unit.PROPORTIONAL), "Beschreibung", "userObject.beschreibung"),
new EditableDropDownChoiceColumn(new ColumnLocation(Alignment.RIGHT, 10, Unit.EM), "Status", "userObject.status", Arrays.asList(TaskStatus
.values())), new AbstractColumn(new ColumnLocation(Alignment.RIGHT, 30, Unit.PX), "") {
public IRenderable newCell(TreeNode node, int level) {
return null;
}
public Component newCell(MarkupContainer parent, String id, final TreeNode node, int level) {
return new LinkPanel(id, REMOVE, node) {
@Override
protected void handle(TreeNode treeNode, AjaxRequestTarget target) {
// Node
DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeNode;
Task nodeTask = (Task) node.getUserObject();
// Parent
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();
Task parentTask = (Task) parent.getUserObject();
// Entferne den Task aus den Subtaks
// parentTask.getSubtasks().remove(
// defaultTreeModel
// .getIndexOfChild(parent, node));
// Entfernung des Knotens und neu rendern
defaultTreeModel.removeNodeFromParent(node);
tree.modelChanged();
tree.updateTree(target);
}
@Override
protected boolean show() {
if (node.getParent() == null) {
return false;
}
return true;
}
};
}
}, new AbstractColumn(new ColumnLocation(Alignment.RIGHT, 30, Unit.PX), "") {
public IRenderable newCell(TreeNode node, int level) {
return null;
}
public Component newCell(MarkupContainer parent, String id, final TreeNode node, int level) {
return new LinkPanel(id, ADD, node) {
@Override
protected void handle(TreeNode treeNode, AjaxRequestTarget target) {
// Node
DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeNode;
Task nodeTask = (Task) node.getUserObject();
// Füge den Task zu den Subtasks hinzu
Task newTask = new Task();
nodeTask.getSubtasks().add(newTask);
defaultTreeModel.insertNodeInto(new DefaultMutableTreeNode(newTask), node, 0);
tree.getTreeState().expandNode(node);
tree.getTreeState().selectNode(node, true);
tree.invalidateAll();
tree.modelChanged();
tree.updateTree(target);
}
@Override
protected boolean show() {
return true;
}
};
}
}, new AbstractColumn(new ColumnLocation(Alignment.RIGHT, 30, Unit.PX), "") {
public IRenderable newCell(TreeNode node, int level) {
return null;
}
public Component newCell(MarkupContainer parent, String id, final TreeNode node, int level) {
return new LinkPanel(id, GO_UP, node) {
@Override
protected void handle(TreeNode node, AjaxRequestTarget target) {
DefaultMutableTreeNode node1 = (DefaultMutableTreeNode) node;
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node1.getParent();
int index = defaultTreeModel.getIndexOfChild(parent, node1);
defaultTreeModel.removeNodeFromParent(node1);
defaultTreeModel.insertNodeInto(node1, parent, index - 1);
tree.getTreeState().expandNode(parent);
tree.invalidateAll();
tree.modelChanged();
tree.updateTree(target);
}
@Override
protected boolean show() {
if (node.getParent() == null || defaultTreeModel.getIndexOfChild(node.getParent(), node) == 0) {
return false;
}
return true;
}
};
}
}, new AbstractColumn(new ColumnLocation(Alignment.RIGHT, 30, Unit.PX), "") {
public IRenderable newCell(TreeNode node, int level) {
return null;
}
public Component newCell(MarkupContainer parent, String id, final TreeNode node, int level) {
return new LinkPanel(id, GO_DOWN, node) {
@Override
protected void handle(TreeNode node, AjaxRequestTarget target) {
DefaultMutableTreeNode node1 = (DefaultMutableTreeNode) node;
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node1.getParent();
int index = defaultTreeModel.getIndexOfChild(parent, node1);
defaultTreeModel.removeNodeFromParent(node1);
defaultTreeModel.insertNodeInto(node1, parent, index + 1);
tree.getTreeState().expandNode(parent);
tree.invalidateAll();
tree.modelChanged();
tree.updateTree(target);
}
@Override
protected boolean show() {
if (node.getParent() == null
|| defaultTreeModel.getIndexOfChild(node.getParent(), node) == defaultTreeModel.getChildCount(node.getParent()) - 1) {
return false;
}
return true;
}
};
}
} };
Form form = new Form("form");
form.setOutputMarkupId(true);
add(form);
//
defaultTreeModel = createTreeModel(tasks);
tree = new TreeTable("treeTable", defaultTreeModel, columns);
tree.setOutputMarkupId(true);
tree.getTreeState().collapseAll();
form.add(tree);
form.add(new AjaxButton("submit") {
@Override
protected void onSubmit(AjaxRequestTarget target, Form form1) {
Task rootTask = getTaskStructure((DefaultMutableTreeNode) defaultTreeModel.getRoot());
taskManager.saveTasks(EditableTreeTablePanel.this.project, rootTask.getSubtasks());
}
});
}
private Task getTaskStructure(DefaultMutableTreeNode treeNode) {
// Zugehörigen Task ermittel
Task task = (Task) ((DefaultMutableTreeNode) treeNode).getUserObject();
// Die Kinder erst löschen
task.getSubtasks().clear();
// und dann neu aufbauen
if (!treeNode.isLeaf()) {
Enumeration<DefaultMutableTreeNode> children = treeNode.children();
while (children.hasMoreElements()) {
task.getSubtasks().add(getTaskStructure(children.nextElement()));
}
}
return task;
}
/**
* @see BaseTreePage#getTree()
*/
protected AbstractTree getTree() {
return tree;
}
/**
* Creates the model that feeds the tree.
*
* @return New instance of tree model.
*/
protected DefaultTreeModel createTreeModel(List<Task> tasks) {
return convertToTreeModel(tasks);
}
private DefaultTreeModel convertToTreeModel(List<Task> tasks) {
DefaultTreeModel model = null;
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(new Task());
add(rootNode, tasks);
model = new DefaultTreeModel(rootNode);
return model;
}
private void add(DefaultMutableTreeNode parent, List<Task> tasks) {
for (Task task : tasks) {
if (!task.getSubtasks().isEmpty()) {
DefaultMutableTreeNode child = new DefaultMutableTreeNode(task);
parent.add(child);
add(child, task.getSubtasks());
} else {
DefaultMutableTreeNode child = new DefaultMutableTreeNode(task);
parent.add(child);
}
}
}
public static class EditableTextFieldColumn extends PropertyEditableColumn {
public EditableTextFieldColumn(ColumnLocation location, String header, String propertyExpression) {
super(location, header, propertyExpression);
}
@Override
public Component newCell(MarkupContainer parent, String id, TreeNode node, int level) {
return new EditablePanel(id, new PropertyModel(node, getPropertyExpression()));
}
}
public static class EditableDropDownChoiceColumn extends PropertyEditableColumn {
private final List values;
public EditableDropDownChoiceColumn(ColumnLocation location, String header, String propertyExpression, List values) {
super(location, header, propertyExpression);
this.values = values;
}
@Override
public Component newCell(MarkupContainer parent, String id, TreeNode node, int level) {
return new DropDownBoxPanel(id, new PropertyModel(node, getPropertyExpression()), values);
}
}
}